package sensorBoard.sensor;

import java.io.IOException;
import java.util.Vector;

import sensorBoard.ISensorBoardComponent;
import server.interfaces.ISensorBoardManager;

import com.CharNotValidException;
import com.Event;
import com.LedsManager;
import com.ParamNotFoundException;
import com.ParamsLabel;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.IAccelerometer3D;
import com.sun.spot.resources.transducers.LEDColor;

/**
 * Provides the access to the node Accelerometer. Provides information about the acceleration values 
 * and builds instances of AccelListener.
 * @author Francesco Aiello, Antonio Guerrieri, Raffaele Gravina
 *
 */
public class AccelerometerSensor implements ISensorBoardComponent {
	
	private byte [] handlableEvents = {Event.ACC_CURRENT, 
			Event.ACC_CURRENT_ALL_AXES,
			Event.ACC_THRESHOLDCHANGED, 
			Event.ACC_THRESHOLDEXCEDEED,
			Event.ACC_TILT,
			Event.ACC_TERMINATION};
	
	IAccelerometer3D acceleratorSensor;
	private ISensorBoardManager sensorBoardManager;
	private Vector accelListeners;

	/**
	 * The constructor needs to know own sensorBoardManager and the Accelerometer class provided by SunSPOT SDK
	 * @param sensorBoardManager own sensorBoardManager
	 */
	public AccelerometerSensor (ISensorBoardManager sensorBoardManager) {
		this.sensorBoardManager = sensorBoardManager;
		this.acceleratorSensor = EDemoBoard.getInstance().getAccelerometer();
		this.accelListeners = new Vector();
		
	}
	
	public boolean IsEventHandlable(byte eventName) {
		for (int i = 0; i < handlableEvents.length; i++) 
			if (this.handlableEvents[i] == eventName)
				return true;
		return false;
	}
	
	public void handleEvent(Event event) {
		
		
		try {
			byte eventName = event.getName();
			switch (eventName) {
				case Event.ACC_TILT:
					if (event.getType() == Event.NOW) {
						event.setParam(ParamsLabel.ACC_TILT_X_VALUE, "" + this.acceleratorSensor.getTiltX());
						event.setParam(ParamsLabel.ACC_TILT_Y_VALUE, "" + this.acceleratorSensor.getTiltY());
						event.setParam(ParamsLabel.ACC_TILT_Z_VALUE, "" + this.acceleratorSensor.getTiltZ());
						this.sensorBoardManager.send(event);
					}
				break;
				case Event.ACC_CURRENT:
					if (event.getType() == Event.NOW) {
						event.setParam(ParamsLabel.ACC_ACCEL_VALUE, "" + this.acceleratorSensor.getAccel());
						this.sensorBoardManager.send(event);
					}
				break;
				case Event.ACC_CURRENT_ALL_AXES:
					if (event.getType() == Event.NOW) {
						event.setParam(ParamsLabel.ACC_ACCEL_X_VALUE, "" + this.acceleratorSensor.getAccelX());
						event.setParam(ParamsLabel.ACC_ACCEL_Y_VALUE, "" + this.acceleratorSensor.getAccelY());
						event.setParam(ParamsLabel.ACC_ACCEL_Z_VALUE, "" + this.acceleratorSensor.getAccelZ());
						this.sensorBoardManager.send(event);
					}
				break;
				case Event.ACC_THRESHOLDEXCEDEED:
					if (event.getType() != Event.NOW && this.accelListeners.size() == 0) {
						String sensorID = this.sensorBoardManager.generateSensorBoardComponentID();
						this.accelListeners.addElement(new AccelListener(this, sensorID, event));
						Event sensorIDEvent = new Event("", event.getTargetID(), Event.TMP_ID, Event.NOW);
						sensorIDEvent.setParam(ParamsLabel.SNS_ID, sensorID);
						this.sensorBoardManager.send(sensorIDEvent);
					}
					else {
						Event sensorBoardComponentNotAvailableEvent = new Event("", event.getTargetID(), Event.ACC_NOT_AVAILABLE, Event.NOW);
						this.sensorBoardManager.send(sensorBoardComponentNotAvailableEvent);
					}
						
				break;
				case Event.TMP_TERMINATION:
					String sensorID;
					try {
						sensorID = event.getParam(ParamsLabel.SNS_ID);
						if (!sensorID.equals("")) {
							if (this.terminateListener(sensorID))
								this.sensorBoardManager.send(event);
						}
					}
					catch (ParamNotFoundException e) {
						LedsManager.error(LEDColor.YELLOW);
						e.printStackTrace();
					}
				break;				
			}
		}
		catch (IOException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
		catch (CharNotValidException e) {
			LedsManager.error(LEDColor.YELLOW);
			e.printStackTrace();
		}
		
	}

	public void send(Event backEvent) {
		this.sensorBoardManager.send(backEvent);
	}
	
	public boolean terminateListener(String sensorID) {
		for (int i = 0; i < this.accelListeners.size(); i++) {
			AccelListener accelListener = (AccelListener)this.accelListeners.elementAt(i);
			if ( accelListener.getSensorBoardComponentID().equals(sensorID) ) {
				this.accelListeners.removeElementAt(i);
				return accelListener.terminateListener(); 
			}
		}
		return false;
	}
}
